﻿using System;
using System.Collections.Generic;
using UnityEngine;

namespace Core
{
    public partial class Entity : IObject
    {
        public long InstanceId;

        public virtual bool IsDisposed => InstanceId == 0;

#if UNITY_EDITOR
        Transform viewTransform = default;
#endif

        private Dictionary<long, Entity> components;
        public Dictionary<long, Entity> Components 
        {
            get=>components ??= new Dictionary<long, Entity>();
        }

        private Dictionary<long, Entity> childrens;
        public Dictionary<long, Entity> Children
        {
            get => childrens ??= new Dictionary<long, Entity>();
        }

        private Entity parent;

        public Entity Parent
        {
            get => parent;
            set
            {
                parent = value;
                if (value != null)
                {
                    Scene = value.scene;
                }
                parent.Children.Add(this.InstanceId, this);
            }
        }

        private Scene scene;

        public Scene Scene
        {
            get => scene;
            set
            {
                scene = value;

                if(value != null)
                {
                    scene.World.EventSystem.RegisterSystem(this);
#if UNITY_EDITOR
                    viewTransform = new GameObject(GetViewName()).transform;
                    viewTransform.SetParent(this.Parent == null ?
                        UnityEngine.GameObject.Find("Global/Scenes").transform : this.Parent.viewTransform);
#endif
                }
            }
        }

        protected virtual string GetViewName()
        {
            return this.GetType().Name;
        }

        public T GetParent<T>() where T : Entity
        {
            return parent as T;
        }

        public T GetComponent<T>() where T : Entity
        {
            if (components == null)
                return default;

            Components.TryGetValue(typeof(T).ToRuntimeId(), out var component);
            return component as T;
        }

        public T GetChild<T>(long id) where T : Entity
        {
            if (childrens == null)
                return default;

            Children.TryGetValue(id, out var entity);
            return entity as T;
        }


        public virtual void Dispose()
        {
#if UNITY_EDITOR
            if(viewTransform != null)
            {
                GameObject.Destroy(viewTransform.gameObject);
                viewTransform = null;
            }
#endif
            InstanceId = 0;
            if(components != null)
            {
                foreach (var component in components.Values)
                {
                    component.Dispose();
                }
                components.Clear();
                components = null;
            }

            if (childrens != null)
            {
                foreach (var children in childrens.Values)
                {
                    children.Dispose();
                }
                childrens.Clear();
                childrens = null;
            }
        }
    }

 
}
